package pers.liu.yibandemo.component;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pers.liu.yibandemo.entity.Admin;
import pers.liu.yibandemo.entity.ChatLog;
import pers.liu.yibandemo.service.AdminService;
import pers.liu.yibandemo.service.ChatLogService;
import pers.liu.yibandemo.service.ParentService;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

// 导入...

@ServerEndpoint(value = "/imserver/{type}/{id}", configurator = WebSocketServer.CustomConfigurator.class)
@Component
public class WebSocketServer {
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    private static final Map<String, Session> adminSessions = new ConcurrentHashMap<>();
    private static final Map<String, Session> parentSessions = new ConcurrentHashMap<>();

    private static ChatLogService chatLogService;  // 修改为 static
    @Autowired
    private ParentService parentService;
    @Autowired
    private AdminService adminService;

    // 无参构造函数
    public WebSocketServer() {}

    // 自定义 Configurator
    public static class CustomConfigurator extends ServerEndpointConfig.Configurator {
        @Override
        public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
            return SpringContext.getBean(clazz);
        }
    }

    // 由于 ChatLogService 现在是静态的，我们使用一个非静态的 setter 方法来注入
    @Autowired
    public void setChatLogService(ChatLogService cls) {
        WebSocketServer.chatLogService = cls;
    }
    @OnOpen
    public void onOpen(Session session, @PathParam("type") String type, @PathParam("id") String id) {
        if ("admin".equals(type)) {
            adminSessions.put(id, session);
        } else if ("parent".equals(type)) {
            parentSessions.put(id, session);
        }
        log.info("新连接：type={}, id={}, 当前管理员在线数：{}, 家长在线数：{}", type, id, adminSessions.size(), parentSessions.size());
        if (adminSessions.size() != 0) {
//            JSONObject result = new JSONObject();
//            JSONArray array = new JSONArray();
//            result.set("users", array);
//            for (Object key : parentSessions.keySet()) {
//                JSONObject jsonObject = new JSONObject();
//                jsonObject.set("userid", key);
//                array.add(jsonObject);
//            }
//            log.info("后台即将发送管理员客户端家长上线信息：{}", JSONUtil.toJsonStr(result));
//            sendAllMessage(JSONUtil.toJsonStr(result));
            sendAllMessage(parentService.getAllParentIdsAsJson());
        }
    }

    @OnClose
    public void onClose(Session session, @PathParam("type") String type, @PathParam("id") String id) {
        if ("admin".equals(type)) {
            adminSessions.remove(id);
        } else if ("parent".equals(type)) {
            parentSessions.remove(id);
        }
        log.info("连接关闭：type={}, id={}, 当前管理员在线数：{}, 家长在线数：{}", type, id, adminSessions.size(), parentSessions.size());
    }

    @OnMessage
    public void onMessage(String message, Session session, @PathParam("type") String type, @PathParam("id") String id) {
        log.info("服务端收到来自type={}, id={}的消息: {}", type, id, message);

        JSONObject obj = JSONUtil.parseObj(message);
        String text = obj.getStr("text");
        String timestamp = obj.getStr("timestamp");

        if ("parent".equals(type)) {
            sendMessageToAllAdmins(id, text, timestamp);
        } else if ("admin".equals(type)) {
            String to = obj.getStr("to");

            Session toParent = parentSessions.get(to);
            if (toParent != null) {
                //发送给前端
                JSONObject jsonObject = new JSONObject();
                jsonObject.set("from", id);
                jsonObject.set("text", text);
                jsonObject.set("timestamp", timestamp);
                this.sendMessage(jsonObject.toString(), toParent);
                log.info("管理员发送给家长类型的id={}，消息：{}" , to, jsonObject);
            }
            // 将聊天记录插入数据库
            ChatLog chatLog = new ChatLog();
            chatLog.setSenderId(Long.valueOf(id));
            chatLog.setSenderType("admin");
            chatLog.setReceiverType("parent");
            chatLog.setReceiverId(Long.valueOf(to));
            chatLog.setMessage(text);
            // 将 ISO 时间字符串解析为 Instant
            Instant instant = Instant.parse(timestamp);
            // 将 Instant 转换为 LocalDateTime（假设您想使用系统默认时区）
            LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
            chatLog.setTimestamp(localDateTime);
            chatLogService.addChatLog(chatLog);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }

    private void sendMessage(String message, Session toSession) {
        try {
            log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }

    private void sendMessageToAllAdmins(String fromParentId, String messageText, String timestamp) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("from", fromParentId);
        jsonObject.set("text", messageText);
        jsonObject.set("timestamp", timestamp);
        log.info("家长{}发送给全部管理员信息{}", fromParentId, messageText);
        String messageToSend = jsonObject.toString();
        //谁在线，谁接受，谁处理
        for (String key : adminSessions.keySet()) {
            Session adminSession = adminSessions.get(key);
            // 发送消息
            sendMessage(messageToSend,adminSession);
            // 将聊天记录插入数据库
            ChatLog chatLog = new ChatLog();
            chatLog.setSenderId(Long.valueOf(fromParentId));
            chatLog.setSenderType("parent");
            chatLog.setReceiverId(Long.valueOf(key));
            chatLog.setReceiverType("admin");
            chatLog.setMessage(messageText);
            // 将 ISO 时间字符串解析为 Instant
            Instant instant = Instant.parse(timestamp);
            // 将 Instant 转换为 LocalDateTime（假设您想使用系统默认时区）
            LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
            chatLog.setTimestamp(localDateTime);
            chatLogService.addChatLog(chatLog);
        }
        //如果没有在线管理员，指定默认管理员插入聊天记录以支持离线发送
        if(adminSessions.isEmpty()){
            Admin admin = adminService.getOneAdmin();
            if(admin!=null){
                ChatLog chatLog = new ChatLog();
                chatLog.setSenderId(Long.valueOf(fromParentId));
                chatLog.setSenderType("parent");
                chatLog.setReceiverId(admin.getAdminId());
                chatLog.setReceiverType("admin");
                chatLog.setMessage(messageText);
                // 将 ISO 时间字符串解析为 Instant
                Instant instant = Instant.parse(timestamp);
                // 将 Instant 转换为 LocalDateTime（假设您想使用系统默认时区）
                LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
                chatLog.setTimestamp(localDateTime);
                chatLogService.addChatLog(chatLog);
            }
        }
    }

    private void sendAllMessage(String message) {
        try {
            for (Session session : adminSessions.values()) {
                log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }
}
